﻿using System;
using System.Collections.Generic;
using System.Linq;
using com.eforceglobal.crux.DTOs;
using com.eforceglobal.crux.BusinessObjects;
using com.eforceglobal.crux.security.EncryptionAndHashing;
using com.eforceglobal.crux.security.EncryptionAndHashing.Enums;
using com.eforceglobal.crux.BusinessObjects.DatabaseQueries;
using com.eforceglobal.crux.notifications;
using com.eforceglobal.crux.logging;
using com.eforceglobal.crux.logging.Enums;
using com.eforceglobal.crux.exceptions;

namespace com.eforceglobal.crux.BusinessFacades
{
    public class UserFacade
    {
        public List<UserInformation> GetUsers(int CompanyID)
        {
            Queries usersQuery = new Queries();
            IEnumerable<UserInformation> users =
                from usersList in usersQuery.GetUsers(CompanyID)
                select ClassConverter.CopyUserToUserInformation(usersList);
            return users.ToList();
        }

        public UserInformation GetUser(int UserID)
        {
            if (UserID == 0) return new UserInformation();
            Queries userQuery = new Queries();
            User user = userQuery.GetUser(UserID);
            return ClassConverter.CopyUserToUserInformation(user);
        }

        public UserInformation GetUser(string UserName)
        {
            Queries userQuery = new Queries();
            User user = userQuery.GetUser(UserName);
            return ClassConverter.CopyUserToUserInformation(user);
        }

        public void SaveUser(UserInformation user, PasswordStorageType passwordstoragetype)
        {
            CheckValidity(user); 
            Queries userQuery = new Queries();
            User dbUser = new User();
            if (user.UserID != 0)
                dbUser = userQuery.GetUser(user.UserID);

            dbUser = ClassConverter.CopyUserInformationToUser(user, dbUser);
            if (user.UserID != 0)
                userQuery.SubmitChanges();
            else
                CreateUser(user, dbUser, userQuery, passwordstoragetype);
        }

        private void CheckValidity(UserInformation user)
        {
            if (UserExistInCompany(user))
                throw CruxExceptionManager.CreateNewDatabaseException("905");
        }

        public bool UserExistInCompany(UserInformation user)
        {
            Queries query = new Queries();
            User dbUser = query.GetUserFromCompany(user.UserName);
            if (dbUser != null && dbUser.UserID != user.UserID)
                return true;
            return false;
        }

        private void CreateUser(UserInformation user, User dbUser, Queries userQuery, PasswordStorageType passwordStorageType)
        {
            KeyValuePair<string, string> RandomAndHashedPassword = GenerateRandomPassword(passwordStorageType);
            string RandomPassword = RandomAndHashedPassword.Key;
            dbUser.Password = RandomAndHashedPassword.Value;
            userQuery.InsertUser(dbUser);
            try
            {
                CreateUserNotification createUserNotification = new CreateUserNotification();
                createUserNotification.SendCreateUserNotificationToUser(user, RandomPassword);
            }
            catch (Exception ex)
            {
                ApplicationLogger.LogApplicationMessage(ex.Message, ApplicationLogType.Notification, ex.StackTrace);
                throw CruxExceptionManager.CreateNewNotificationException("701");
            }
        }

        private KeyValuePair<string, string> GenerateRandomPassword(PasswordStorageType passwordStorageType)
        {
            //TODO: Improove Password Generation Mechanism. First Six Characters Of Guid Are A Neat Idea
            //but find out how the rest of the world does it. .NET is supposed to have some API for this
            //becuase the membership providers renegrate forgotten passwords. 

            Guid randomKey = Guid.NewGuid();
            string randomPassword = randomKey.ToString().Substring(0, 6);
            string randomHashedPassword = randomPassword;
            if (passwordStorageType == PasswordStorageType.hashed)
                randomHashedPassword = Hasher.GetHash(randomPassword);
            KeyValuePair<string, string> NormalAndHashedPassword = new KeyValuePair<string, string>(randomPassword, randomHashedPassword);
            return NormalAndHashedPassword;
        }

        public void DeleteUser(int UserID)
        {
            Queries userQuery = new Queries();
            User user = userQuery.GetUser(UserID);
            userQuery.DeleteUser(user);
        }
    }
}
